package fi.helsinki.cs.ohtu10k.view;
import fi.helsinki.cs.ohtu10k.schedule.*;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;

import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JComboBox;
import javax.swing.JButton;
import javax.swing.ToolTipManager;

import java.awt.event.*;

import org.joda.time.DateTime;
import org.joda.time.Duration;

/**
 * Class implementing the grid panel for week view. 
 * @author Simo Hellsten
 *
 */
@SuppressWarnings("serial")
public class WeekPanel extends JPanel {
        
        private ArrayList<Shape> slots;
        private ArrayList<WeekGridLabel> labels;
        private ArrayList<JLabel> eventLabels;
        private DateTime activeDate; 
        private DateTime activeWeekFirstDate; 
        private ScheduleManager schedule;
        private ScheduleEvent[] eventList;
        
        private String[] weekdays = {"maanantai", "tiistai", "keskiviikko", "torstai", "perjantai", "lauantai", "sunnuntai"};
        private String[] selectableWeeks;
        JComboBox weekSelector;
        JButton next, prev, current;
        int dayWidth, hourHeight, labelWidth, labelHeight, hoursPerDay, firstHour, offsetX, offsetY;
        
        public WeekPanel(int dayWidth, int hourHeight, int labelWidth, int labelHeight, int hoursPerDay, int firstHour, int offsetX, int offsetY) {
/* Store dimensions from parameters */
        	
        	this.dayWidth = dayWidth;
        	this.hourHeight = hourHeight;
        	this.labelWidth = labelWidth;
        	this.labelHeight = labelHeight;
        	this.hoursPerDay = hoursPerDay;
        	this.firstHour = firstHour;
        	this.offsetX = offsetX;
        	this.offsetY = offsetY;
        	
        	
        	eventLabels = new ArrayList<JLabel>();
        	activeDate = new DateTime();
        	activeWeekFirstDate = activeDate.withDayOfWeek(1);
            slots = new ArrayList<Shape>();
            labels = new ArrayList<WeekGridLabel>();
            this.setLayout(null);
            this.setOpaque(false);
            ToolTipManager.sharedInstance().setInitialDelay(0);
            for (int hours=0;hours<hoursPerDay;hours++) {
            	slots.add(new Rectangle2D.Float(offsetX, 40+offsetY+labelHeight+hours*hourHeight, labelWidth, hourHeight));
            	labels.add(new WeekGridLabel(""+(hours+firstHour)+"-"+(hours+firstHour+1), offsetX+2, 40+offsetY+labelHeight+hourHeight-5+hours*hourHeight));
            }
            for (int days=0;days<7;days++) {
            	slots.add(new Rectangle2D.Float(offsetX+labelWidth+days*dayWidth, 40+offsetY, dayWidth, labelHeight));
            	labels.add(new WeekGridLabel(weekdays[days], offsetX+2+labelWidth+days*dayWidth, 40+offsetY+labelHeight/2-5));
            	labels.add(new WeekGridLabel(activeWeekFirstDate.plusDays(days).dayOfMonth().getAsString()+"."+activeWeekFirstDate.plusDays(days).monthOfYear().getAsString()+".", offsetX+2+labelWidth+days*dayWidth, 40+offsetY+labelHeight-5));
            	for (int hours=0;hours<hoursPerDay;hours++)
            		slots.add(new Rectangle2D.Float(offsetX+labelWidth+days*dayWidth, 40+offsetY+labelHeight+hours*hourHeight, dayWidth, hourHeight));
            }
                            
                selectableWeeks = new String[52];
                for (int i=0; i<52; ++i) {
                	selectableWeeks[i] = new DateTime().withWeekOfWeekyear(i+1).withDayOfWeek(1).dayOfMonth().getAsString() 
                	+"."+ new DateTime().withWeekOfWeekyear(i+1).withDayOfWeek(1).monthOfYear().getAsString() +". - "
                	+ new DateTime().withWeekOfWeekyear(i+1).withDayOfWeek(7).dayOfMonth().getAsString() +"."
                	+ new DateTime().withWeekOfWeekyear(i+1).withDayOfWeek(7).monthOfYear().getAsString() +"."
                	+ " (vko "+ (i+1) +")";
                }
                
                prev = new JButton("<<");
                weekSelector = new JComboBox(selectableWeeks);
                next = new JButton(">>");
                current = new JButton("Tämä viikko");
                
                weekSelector.setSelectedIndex(activeDate.getWeekOfWeekyear()-1);

                prev.addActionListener(new ActionListener(){
                    public void actionPerformed(ActionEvent e){
                    	if (activeDate.getWeekOfWeekyear() > 1) {
                    		setActiveDate(activeDate.minusDays(7));
                    	}
                    }});
                weekSelector.addActionListener(new ActionListener(){
                    public void actionPerformed(ActionEvent e){
                    	setActiveDate(activeDate.withWeekOfWeekyear(weekSelector.getSelectedIndex()+1));
                    }});
                next.addActionListener(new ActionListener(){
                    public void actionPerformed(ActionEvent e){
                    	if (activeDate.getWeekOfWeekyear() < 52) {
                    		setActiveDate(activeDate.plusDays(7));
                    	}
                    }});
                current.addActionListener(new ActionListener(){
                    public void actionPerformed(ActionEvent e){
                    	setActiveDate(new DateTime());
                    }});
               
                prev.setBounds(offsetX, offsetY, 55, 25);
                weekSelector.setBounds(offsetX+57, offsetY, 200, 25);
                next.setBounds(offsetX+259, offsetY, 55, 25);
                current.setBounds(offsetX+335, offsetY, 120, 25);
                this.add(prev);                         
                this.add(weekSelector);                         
                this.add(next);                         
                this.add(current);                         

                /* Testitapahtuma *//*
                schedule = ScheduleManagerHandler.getScheduleManager();
                schedule.addCourse(new DateTime(), new DateTime().plusDays(7), "umpahpah", "pah");
                ScheduleCourse[] courses = schedule.getCourses();
                schedule.addEvent(new DateTime(), new Duration(7200000), "Umpah", courses[0] , false);
                *//* Testi loppuu */
                
                updateEvents();                
        }
        public void setActiveDate(DateTime d) {
        	activeDate = d;        	
        	activeWeekFirstDate = d.withDayOfWeek(1);        	
        	
        	labels.clear();
            for (int hours=0;hours<hoursPerDay;hours++) {
                labels.add(new WeekGridLabel(""+(hours+firstHour)+"-"+(hours+firstHour+1), offsetX+2, 40+offsetY+labelHeight+hourHeight-5+hours*hourHeight));
                }
            for (int days=0;days<7;days++) {
            	labels.add(new WeekGridLabel(weekdays[days], offsetX+2+labelWidth+days*dayWidth, 40+offsetY+labelHeight/2-5));
            	labels.add(new WeekGridLabel(activeWeekFirstDate.plusDays(days).dayOfMonth().getAsString()+"."+activeWeekFirstDate.plusDays(days).monthOfYear().getAsString()+".", offsetX+2+labelWidth+days*dayWidth, 40+offsetY+labelHeight-5));
            	}

    		prev.setEnabled(true);
    		next.setEnabled(true);
            
        	if (activeDate.getWeekOfWeekyear() == 1)
        		prev.setEnabled(false);
        	if (activeDate.getWeekOfWeekyear() == 52)
        		next.setEnabled(false);
            weekSelector.setSelectedIndex(activeDate.getWeekOfWeekyear()-1);
            updateEvents();                
            repaint();            
        }
        public void updateEvents() {
        	String courseName;
            schedule = ScheduleManagerHandler.getScheduleManager();
            eventList = schedule.getEvents(activeWeekFirstDate.withHourOfDay(0), activeWeekFirstDate.withDayOfWeek(7).withHourOfDay(23));
            for (JLabel e: eventLabels) {
                this.remove(e);                            
            }        	
            eventLabels.clear();
            for (ScheduleEvent e: eventList) {
            	if (e.getCourse() != null)
            		 courseName = "<br>"+e.getCourse().getName();
            	else
            		courseName = "";
            	JLabel l = new JLabel("<html>"+e.getStartDate().hourOfDay().get()+"."+String.format("%02d",e.getStartDate().minuteOfHour().get())+"-"+(e.getStartDate().plusSeconds((int)e.getDuration().getStandardSeconds())).hourOfDay().get()+"."+String.format("%02d",(e.getStartDate().plusSeconds((int)e.getDuration().getStandardSeconds())).minuteOfHour().get())+courseName+"<br>"+e.getName()+"<html>");
            	l.setBounds(offsetX+labelWidth+dayWidth*((e.getStartDate().dayOfWeek()).get()-1)+1,40+offsetY+labelHeight+(int)(hourHeight/(float)60*(float)e.getStartDate().minuteOfHour().get())+hourHeight*(e.getStartDate().hourOfDay().get()-firstHour)+1,dayWidth-1,(int)(hourHeight*(float)e.getDuration().getStandardSeconds()/(float)3600)-1);
            	l.setToolTipText("<html>"+e.getStartDate().dayOfMonth().getAsString()+"."+e.getStartDate().monthOfYear().getAsString()+". klo "+e.getStartDate().hourOfDay().get()+"."+String.format("%02d",e.getStartDate().minuteOfHour().get())+"-"+(e.getStartDate().plusSeconds((int)e.getDuration().getStandardSeconds())).hourOfDay().get()+"."+String.format("%02d",(e.getStartDate().plusSeconds((int)e.getDuration().getStandardSeconds())).minuteOfHour().get())+courseName+"<br>"+e.getName()+"<html>");
            	
            	l.setOpaque(true);
            	if (e.isNotifiable())
            		l.setBackground(Color.red);
            	else
            		l.setBackground(Color.yellow);
            	eventLabels.add(l);                     
            }
            for (JLabel e: eventLabels) {
                this.add(e);                            
            }        	
        }
        public DateTime getActiveDate() {
        	return activeDate;        	
        }
        public DateTime getActiveWeekFirstDate() {
        	return activeWeekFirstDate;        	
        }
        public ScheduleEvent[] getActiveWeekEvents() {
        	return eventList;        	
        }
        public void paintComponent(Graphics g) {
        		super.paintComponent(g);
                Graphics2D g2d = (Graphics2D) g;
                for (Shape s : slots) {
                        g2d.draw(s);
                }
                for (WeekGridLabel l : labels) {
                        g2d.drawString(l.s, l.x, l.y);
                }
        }
        
}